// Copyright (C) 2023 即时通讯网(52im.net) & Jack Jiang.
// The RainbowChat Project. All rights reserved.
// 
// 【本产品为著作权产品，合法授权后请放心使用，禁止外传！】
// 【本次授权给：<北京小羊驼科技有限公司>，授权编号：<NT231212144350>，代码指纹：<A.702363430.550>，技术对接人微信：<ID: wxid_wbyootvkdcgj22>】
// 【授权寄送：<收件：苏先生、地址：北京市大兴区北京密码西区6号楼1单元301、电话：18613885610、邮箱：bd@huiyuanxiang-inc.com>】
// 
// 【本系列产品在国家版权局的著作权登记信息如下】：
// 1）国家版权局登记名(简称)和权证号：RainbowChat    （证书号：软著登字第1220494号、登记号：2016SR041877）
// 2）国家版权局登记名(简称)和权证号：RainbowChat-Web（证书号：软著登字第3743440号、登记号：2019SR0322683）
// 3）国家版权局登记名(简称)和权证号：RainbowAV      （证书号：软著登字第2262004号、登记号：2017SR676720）
// 4）国家版权局登记名(简称)和权证号：MobileIMSDK-Web（证书号：软著登字第2262073号、登记号：2017SR676789）
// 5）国家版权局登记名(简称)和权证号：MobileIMSDK    （证书号：软著登字第1220581号、登记号：2016SR041964）
// * 著作权所有人：江顺/苏州网际时代信息科技有限公司
// 
// 【违法或违规使用投诉和举报方式】：
// 联系邮件：jack.jiang@52im.net
// 联系微信：hellojackjiang
// 联系QQ号：413980957
// 授权说明：http://www.52im.net/thread-1115-1-1.html
// 官方社区：http://www.52im.net
package com.x52im.rbchat.network.im;

import java.util.ArrayList;

import net.x52im.mobileimsdk.server.protocal.Protocal;
import net.x52im.mobileimsdk.server.protocal.ProtocalType;
import android.content.Context;
import android.util.Log;

import com.x52im.rbchat.IMClientManager;
import com.x52im.rbchat.MyApplication;
import com.x52im.rbchat.cache.MessagesProvider;
import com.x52im.rbchat.logic.chat_root.model.Message;
import com.x52im.rbchat.logic.chat_root.model.Message.SendStatus;

public class MessageQoSHelper {
	private final static String TAG = MessageQoSHelper.class.getSimpleName();
	
	//---------------------------------------------------------------------------------- 处理丢包相关方法 START
	/**
	 * 处理发送失败的消息.
	 * 
	 * @param lostMessages
	 * @return
	 */
	public static void processMessagesLost_forLoverChat(Context context, ArrayList<Protocal> lostMessages) {
		IMClientManager imc = MyApplication.getInstance2().getIMClientManager();

		// 是否需要更新ui
		boolean needUpdateUI = false;
		
		// 遍历丢包列表
		for(int i = lostMessages.size() - 1; i >= 0; i--)// 注意：匹配的同时又要删除集合内容的话，通常是从列表尾遍历，否则会产生bug哦！
		{
			Protocal lostP = lostMessages.get(i);
			if(lostP != null) {
				// 找到该应答包对应的目标消息了吗？
				boolean beMatched = false;
				
				// ** 通用数据（除聊天框架的保留指令外的所有消都属通用数据）
				if(lostP.getType() == ProtocalType.C.FROM_CLIENT_TYPE_OF_COMMON$DATA) {
					Log.d(TAG, "【QoS】[正式聊天]====当前待决消息ghost列表中共有"+imc.getMessagesProvider().getAllFriendsMessagesGhostForNoReceived().size()+"条未决的消息=====");

					// v2.0新启用的此算法（直接从待决列表中匹配，而非遍历所有好友的所有消息，则计算效率要高很多罗!）
					Message cme = imc.getMessagesProvider().getAllFriendsMessagesGhostForNoReceived().get(lostP.getFp());
					if(cme != null) {
						// 找到了
						beMatched = true;
						// 更新UI标识
						cme.setSendStatus(SendStatus.sendFaild);
						// 需要更新Ui
						needUpdateUI = true;
						// 本次匹配结束
						Log.d(TAG, "【QoS】[正式聊天]指纹是"+lostP.getFp()+"的丢包在待决消息ghost列表里，本次成功匹配到丢包目标哦.");
					} else
						Log.w(TAG, "【QoS】[正式聊天]指纹是"+lostP.getFp()+"的丢包不在AllFriendsMessagesGhostForNoReceived的消息记录里.");
				} else
					Log.w(TAG, "【QoS】[正式聊天]目前不能支持协议类型="+lostP.getType()+"的丢包处理哦~！！");

				if(beMatched) {
					// 移除丢包列表中已匹配的（已处理完成的）
					lostMessages.remove(i); // 注意：匹配的同时又要删除集后的话，通常是从列表尾遍历，否则会产生bug哦！
					// 移除待决列表中的包
					imc.getMessagesProvider().sendToFriendFaild(lostP.getFp());
				}
			}
		}

		// 本批丢包消息处理完成了，但要及时通知UI更新哦
		if(needUpdateUI) {
//			// 本批丢包消息处理完成了，但要及时通知UI更新哦
//			if(lostMessages.size() > 0)
			{
				// 遍历所有好友的消息：
				// 因为目前为了提丢包消息匹配的效率，所以不用对所有好友消息进行遍历，而只需要像上面代码一样只要针对未
				// 决包列表进行匹配即可，而这样就无法找到丢包的消息对应的是谁的消息，那么也就没办法精确通知它的Ui观察
				// 者了。不过干脆就这样尝试通知所有消息所有者的观察者吧，性能也没有多大损失，但UI更新的目的也达到了！
				imc.getMessagesProvider().notifyAllObserver();
			}
		}
		
//		return beMatched;
	}

	/**
	 * BBS公聊消息或普通群聊消息的丢包处理.
	 * <p>
	 * <b>重要说明：</b>本方法完全copy自 {@link #processMessagesLost_forLoverChat(Context, ArrayList)}，请注意同步！
	 * 
	 * @param lostMessages
	 * @return
	 */
	public static void processMessagesLost_forGroupChat(Context context, ArrayList<Protocal> lostMessages) {
		// 是否需要更新ui
		boolean needUpdateUI = false;
		
		MessagesProvider mp = MyApplication.getInstance2().getIMClientManager().getGroupsMessagesProvider();
		
		// 非null检查
		if(mp == null)
			return;
		
		// 遍历丢包列表
		for(int i = lostMessages.size() - 1; i >= 0; i--)// 注意：匹配的同时又要删除集后的话，通常是从列表尾遍历，否则会产生bug哦！
		{
			Protocal lostP = lostMessages.get(i);
			if(lostP != null) {
				// 找到该应答包对应的目标消息了吗？
				boolean beMatched = false;
				
				// ** 通用数据（除聊天框架的保留指令外的所有消都都属通用数据）
				if(lostP.getType() == ProtocalType.C.FROM_CLIENT_TYPE_OF_COMMON$DATA) {
					Log.d(TAG, "【QoS】[BBS/群聊]====当前待决消息ghost列表中共有"+mp.getAllFriendsMessagesGhostForNoReceived().size()+"条未决的消息=====");

					// v2.0 新启用的此算法（直接从待决列表中匹配，而非遍历所有好友的所有消息，则计算效率要高很多罗!）
					Message cme = mp.getAllFriendsMessagesGhostForNoReceived().get(lostP.getFp());
					if(cme != null) {
						// 找到了
						beMatched = true;
						// 更新UI标识对方已收到消息了！！
						cme.setSendStatus(SendStatus.sendFaild);//false);
						// 需要更新Ui
						needUpdateUI = true;
						// 本次匹配结束
						Log.d(TAG, "【QoS】[BBS/群聊]指纹是"+lostP.getFp()+"的丢包在待决消息ghost列表" + "里，本次成功匹配到丢包目标哦.");
					} else
						Log.w(TAG, "【QoS】[BBS/群聊]指纹是"+lostP.getFp()+"的丢包不在AllFriendsMessagesGhostForNoReceived的消息记录里.");
				} else
					Log.w(TAG, "【QoS】[BBS/群聊]目前不能支持协议类型="+lostP.getType()+"的丢包处理哦~！！");

				if(beMatched) {
					// 移除丢包列表中已匹配的（已处理完成的）
					lostMessages.remove(i); // 注意：匹配的同时又要删除集后的话，通常是从列表尾遍历，否则会产生bug哦！
					// 移除待决列表中的包
					mp.sendToFriendFaild(lostP.getFp());
				}
			}
		}

		// 本批丢包消息处理完成了，但要及时通知UI更新哦
		if(needUpdateUI) {
//			// 本批丢包消息处理完成了，但要及时通知UI更新哦
//			if(lostMessages.size() > 0)
			{
				// 遍历所有好友的消息：
				// 因为目前为了提丢包消息匹配的效率，所以不用对所有好友消息进行遍历，而只需要像上面代码一样只要针对
				// 未决包列表进行匹配即可，而这样就无法找到丢包的消息对应的是谁的消息，那么也就没办法精确通知它的Ui
				// 观察者了。不过干脆就这样尝试通知所有消息所有者的观察者吧，性能也没有多大损失，但UI更新的目的也达到了！
				mp.notifyAllObserver();
			}
		}
		
//		return beMatched;
	}
	//---------------------------------------------------------------------------------- 处理丢包相关方法 END
	
	//---------------------------------------------------------------------------------- 处理应答包相关方法 START
	/**
	 * 收到正式聊天消息的应答包时的处理.
	 * 
	 * @param theFingerPrint
	 * @return
	 */
	public static boolean processMessagesBeReceived_forLoverChat(Context context, String theFingerPrint) {
		IMClientManager imc = MyApplication.getInstance2().getIMClientManager();

		// 找到该应答包对应的目标消息了吗？
		boolean beMatched = false;
					
		// v2.0新启用的此算法（直接从待决列表中匹配，而非遍历所有好友的所有消息，则计算效率要高很多罗!）
		Message cme = imc.getMessagesProvider().getAllFriendsMessagesGhostForNoReceived().get(theFingerPrint);
		if(cme != null) {
			// 找到了
			beMatched = true;
			// 更新UI标识对方已收到消息了！！
			cme.setSendStatus(SendStatus.beReceived);
			// 遍历所有好友的消息：
			// 因为目前为了提丢包消息匹配的效率，所以不用对所有好友消息进行遍历，而只需要像上面代码一样只要针对未决包
			// 列表进行匹配即可，而这样就无法找到丢包的消息对应的是谁的消息，那么也就没办法精确通知它的Ui观察者了。不
			// 过干脆就这样尝试通知所有消息所有者的观察者吧，性能也没有多大损失，但UI更新的目的也达到了！
			imc.getMessagesProvider().notifyAllObserver();

			// 本次匹配结束
			Log.d(TAG, "【QoS】[正式聊天]指纹是"+theFingerPrint+"的应答包在待决聊天消息ghost列表里，本次成功匹配到应答包目标哦.");
		} else
			Log.w(TAG, "【QoS】[正式聊天]指纹是"+theFingerPrint+"的应答包不在待决聊天消息ghost列表里.");

		if(beMatched)
			// 移除待决列表中的包，收到消息了就把它从待决列表中去掉哦
			imc.getMessagesProvider().friendReceivedMessage(theFingerPrint);
		
		return beMatched;
	}
	
	/**
	 * 收到BBS聊天消息或普通群聊消息的应答包时的处理.
	 * <p>
	 * <b>重要说明：</b>本方法完全copy自 {@link #processMessagesBeReceived_forLoverChat(Context, String)}，请注意同步！
	 * 
	 * @param theFingerPrint
	 * @return
	 * @see #processMessagesBeReceived_forLoverChat(Context, String)
	 */
	public static boolean processMessagesBeReceived_forGroupChat(Context context, String theFingerPrint) {
		// 找到该应答包对应的目标消息了吗？
		boolean beMatched = false;
		
		MessagesProvider mp = MyApplication.getInstance2().getIMClientManager().getGroupsMessagesProvider();
		
		// 非null检查
		if(mp == null)
			return beMatched;
					
		// 2013-12-18日新启用的此算法（直接从待决列表中匹配，而非遍历所有好友的所有消息，则计算效率要高很多罗!）
		Message cme = mp.getAllFriendsMessagesGhostForNoReceived().get(theFingerPrint);
		if(cme != null) {
			// 找到了
			beMatched = true;
			// 更新UI标识对方已收到消息了！！
			cme.setSendStatus(SendStatus.beReceived);
			// 遍历所有好友的消息：
			// 因为目前为了提升丢包消息匹配的效率，所以不用对所有好友消息进行遍历，而只需要像上面代码一样只要针对未决包
			// 列表进行匹配即可，而这样就无法找到丢包的消息对应的是谁的消息，那么也就没办法精确通知它的Ui观察者了。不
			// 过干脆就这样尝试通知所有消息所有者的观察者吧，性能也没有多大损失，但UI更新的目的也达到了！
			mp.notifyAllObserver();

			// 本次匹配结束
			Log.d(TAG, "【QoS】[BBS/群聊]指纹是"+theFingerPrint+"的应答包在待决聊天消息ghost列表里，本次成功匹配到应答包目标哦.");
		} else
			Log.w(TAG, "【QoS】[BBS/群聊]指纹是"+theFingerPrint+"的应答包不在待决聊天消息ghost列表里.");

		if(beMatched)
			// 移除待决列表中的包，收到消息了就把它从待决列表中去掉哦
			mp.friendReceivedMessage(theFingerPrint);
		
		return beMatched;
	}
	//---------------------------------------------------------------------------------- 处理应答包相关方法 END

}
